package com.csu54sher.basereservation.util;


import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.csu54sher.basereservation.constant.JWTClaimConstant;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Slf4j
public class JWTUtil {
    /**
     * 创建token
     * @param secretKey 密钥
     * @param ttlMillis 过期时间
     * @param idNumber 学号/工号
     * @return  token
     * @author liuke
     */
    public static String createToken(String secretKey, Long ttlMillis, String idNumber){
        return JWT.create()
                .withClaim(JWTClaimConstant.USER_SCHOOL_ID, idNumber)//用户有效信息
                .withIssuedAt(new Date())//创建时间
                .withExpiresAt(new Date(System.currentTimeMillis() + ttlMillis))//过期时间
                .sign(Algorithm.HMAC256(secretKey.getBytes(StandardCharsets.UTF_8)));//签名（加密算法加密密码,密码默认采用UTF8）
    }

    /**
     * 解析并验证 token
     * @param token     要解析的 JWT 字符串
     * @param secretKey 密钥（必须与生成时一致）
     * @return DecodedJWT 对象（可获取任意 claim）
     * @throws JWTVerificationException 如果 token 过期、无效或签名错误会抛异常
     * @author liuke
     */
    public static DecodedJWT verifyToken(String token, String secretKey) throws JWTVerificationException {
        // 创建验证器（使用相同算法与密钥）
        JWTVerifier verifier = JWT
                .require(Algorithm.HMAC256(secretKey.getBytes(StandardCharsets.UTF_8)))
                .build();
        // 验证并解析
        return verifier.verify(token);
    }

    /**
     * 从 token 中获取学号/工号（USER_SCHOOL_ID）
     * @param token     JWT 字符串
     * @param secretKey 密钥
     * @return 学号（若 token 无效或过期将抛出异常）
     */
    public static String getIdNumber(String token, String secretKey) {
        DecodedJWT decodedJWT = verifyToken(token, secretKey);
        return decodedJWT.getClaim(JWTClaimConstant.USER_SCHOOL_ID).asString();
    }
}
